Working with List and ArrayList in Java
Course: Core Java Training
Topic: Working with List and ArrayList
Course Link: Core Java Training Course
Demo Link: Register for a Course Demo
Website: JustAcademy Official Website
1. Introduction to List and ArrayList
In Java, the List interface and the ArrayList class are important parts of the Java Collections Framework. They are used to store and manage an ordered group of elements. Unlike a Set, a List generally allows duplicate elements and provides index-based access to its contents.
The List interface defines operations that a list should support, while ArrayList is a concrete implementation that stores elements using a resizable array.
For example, a student management system can use an ArrayList to store student names, retrieve a name by its position, add new students, update existing entries, and remove students when necessary.
Why Use List and ArrayList?
- To store multiple values in a single variable.
- To maintain elements in a defined sequence.
- To access elements using zero-based indexes.
- To add, update, and remove elements dynamically.
- To store duplicate values when required.
- To iterate through elements using loops and iterators.
- To simplify data management in Java applications.
2. Learning Objectives
After studying this topic, you should be able to:
- Understand the purpose of the List interface.
- Explain how ArrayList implements List.
- Create and initialize ArrayList objects.
- Add, retrieve, update, and remove elements.
- Search for elements and find their indexes.
- Iterate through lists using different approaches.
- Sort lists and perform common collection operations.
- Understand generics, capacity, performance, and common errors.
- Apply List and ArrayList in practical Java programs.
3. What Is the List Interface?
The List interface belongs to the java.util package. It represents an ordered collection that allows elements to be accessed by their position. Most List implementations permit duplicates, and some also permit null elements.
Because List is an interface, you cannot instantiate it directly using new List<>(). Instead, you create an object of a class that implements the interface.
Example
import java.util.ArrayList;
import java.util.List;
public class ListIntroduction {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Aarav");
names.add("Priya");
names.add("Rahul");
System.out.println(names);
}
}
Output:
[Aarav, Priya, Rahul]
In this example, List<String> defines the variable type, while ArrayList<String> creates the actual object.
4. What Is ArrayList?
ArrayList is a resizable-array implementation of the List interface. It automatically manages the underlying array as elements are added or removed. Unlike a traditional array, an ArrayList can grow beyond its initial capacity.
ArrayList supports duplicate elements and permits null values. It is not synchronized, so it does not automatically provide thread-safe access for concurrent modifications by multiple threads.
Important Characteristics
- Maintains the order in which elements are inserted.
- Allows duplicate elements.
- Supports access through indexes.
- Can grow and shrink as elements are added and removed.
- Provides efficient index-based reads in typical use.
- May require shifting elements when inserting or removing at positions within the list.
- Implements the
RandomAccess marker interface.
- Belongs to the
java.util package.
5. Difference Between List and ArrayList
| Feature |
List |
ArrayList |
| Type |
Interface |
Concrete class |
| Purpose |
Defines list operations. |
Implements list operations using a resizable array. |
| Object creation |
Cannot be instantiated directly. |
Can be instantiated with a constructor. |
| Declaration |
List<String> names; |
ArrayList<String> names; |
| Implementation |
Can be implemented by ArrayList, LinkedList, and other classes. |
Provides a specific list implementation. |
| Flexibility |
Allows implementation changes without changing the declared interface type. |
Ties the declared variable type to ArrayList if used directly. |
Best practice: Declare variables using the List interface when you do not need ArrayList-specific functionality.
List<String> names = new ArrayList<>();
This approach makes it easier to change the implementation later, for example to LinkedList, if the application's requirements change.
6. Importing List and ArrayList
The List interface and ArrayList class are available in the java.util package. Import them before using them in a Java program.
import java.util.List;
import java.util.ArrayList;
You can also import all public types in the package using import java.util.*;, although explicit imports often make dependencies easier to identify.
7. Creating an ArrayList
There are several ways to create an ArrayList, depending on whether the list should start empty, contain initial values, or use an existing collection.
7.1 Creating an Empty ArrayList
import java.util.ArrayList;
import java.util.List;
public class EmptyListExample {
public static void main(String[] args) {
List<String> courses = new ArrayList<>();
courses.add("Java");
courses.add("SQL");
System.out.println(courses);
}
}
Output:
[Java, SQL]
7.2 Creating an ArrayList with Initial Values
import java.util.ArrayList;
import java.util.List;
public class InitialValuesExample {
public static void main(String[] args) {
List<String> languages = new ArrayList<>(
List.of("Java", "Python", "JavaScript")
);
System.out.println(languages);
}
}
Output:
[Java, Python, JavaScript]
The ArrayList created here is modifiable. The List.of() factory method itself returns an unmodifiable list, but passing it to the ArrayList constructor creates a separate, modifiable list containing the same elements.
7.3 Creating an ArrayList with Initial Capacity
ArrayList<Integer> numbers = new ArrayList<>(20);
The value 20 specifies the initial capacity, not the number of elements. The list remains empty until elements are added.
8. Adding Elements to an ArrayList
The add() method inserts elements into an ArrayList. You can append an element to the end or insert it at a specific index.
8.1 Using add(element)
import java.util.ArrayList;
import java.util.List;
public class AddExample {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Mango");
System.out.println(fruits);
}
}
Output:
[Apple, Banana, Mango]
8.2 Using add(index, element)
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Mango");
fruits.add(1, "Banana");
System.out.println(fruits);
Output:
[Apple, Banana, Mango]
The element is inserted at index 1, and the elements previously at that index and later positions shift to the right.
8.3 Adding Multiple Elements
List<String> first = new ArrayList<>();
first.add("Java");
first.add("Python");
List<String> second = new ArrayList<>();
second.add("SQL");
second.add("HTML");
first.addAll(second);
System.out.println(first);
Output:
[Java, Python, SQL, HTML]
9. Accessing Elements with get()
The get(index) method returns the element at a specified position. List indexes start at zero.
List<String> colors = new ArrayList<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");
System.out.println(colors.get(0));
System.out.println(colors.get(2));
Output:
Red
Blue
For a list with three elements, valid indexes are 0, 1, and 2. Accessing an invalid index results in an IndexOutOfBoundsException.
10. Updating Elements with set()
The set(index, element) method replaces the element at a specified index. It does not increase the list's size.
List<String> cities = new ArrayList<>();
cities.add("Mumbai");
cities.add("Pune");
cities.add("Delhi");
cities.set(1, "Nashik");
System.out.println(cities);
Output:
[Mumbai, Nashik, Delhi]
The element at index 1 is replaced. The original list size remains three.
11. Removing Elements from ArrayList
ArrayList provides methods to remove an element by its index or by matching its value.
11.1 Removing by Index
List<String> names = new ArrayList<>();
names.add("Aarav");
names.add("Priya");
names.add("Rahul");
names.remove(1);
System.out.println(names);
Output:
[Aarav, Rahul]
11.2 Removing by Value
List<String> names = new ArrayList<>();
names.add("Aarav");
names.add("Priya");
names.add("Rahul");
names.remove("Priya");
System.out.println(names);
Output:
[Aarav, Rahul]
11.3 Removing All Elements
List<String> names = new ArrayList<>();
names.add("Aarav");
names.add("Priya");
names.clear();
System.out.println(names);
System.out.println(names.isEmpty());
Output:
[]
true
Important Note for Integer Lists
When working with List<Integer>, the call remove(1) removes the element at index 1, not necessarily the integer value 1. Use remove(Integer.valueOf(1)) to remove the value 1.
List<Integer> numbers = new ArrayList<>(
List.of(1, 2, 3, 1)
);
numbers.remove(Integer.valueOf(1));
System.out.println(numbers);
Output:
[2, 3, 1]
This removes the first occurrence of the value 1.
12. Finding the Size of an ArrayList
The size() method returns the number of elements currently stored in the list.
List<String> subjects = new ArrayList<>();
subjects.add("Java");
subjects.add("SQL");
subjects.add("Python");
System.out.println("Total subjects: " + subjects.size());
Output:
Total subjects: 3
Remember that size() reports the number of elements, while capacity refers to the size of the internal storage array. Capacity is not directly exposed as the list's size.
13. Searching Elements in an ArrayList
ArrayList supports methods for checking whether an element exists and for finding the positions of matching values.
| Method |
Description |
contains(value) |
Returns true if an equal element exists. |
indexOf(value) |
Returns the index of the first matching element, or -1 if absent. |
lastIndexOf(value) |
Returns the index of the last matching element, or -1 if absent. |
Example
List<String> tools = new ArrayList<>();
tools.add("Eclipse");
tools.add("IntelliJ");
tools.add("VS Code");
tools.add("IntelliJ");
System.out.println(tools.contains("Eclipse"));
System.out.println(tools.indexOf("IntelliJ"));
System.out.println(tools.lastIndexOf("IntelliJ"));
System.out.println(tools.indexOf("NetBeans"));
Output:
true
1
3
-1
14. Iterating Through an ArrayList
Iteration allows a program to process every element in a list. Java provides several ways to iterate through an ArrayList.
14.1 Using a Standard for Loop
List<String> names = new ArrayList<>(
List.of("Aarav", "Priya", "Rahul")
);
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
14.2 Using an Enhanced for Loop
for (String name : names) {
System.out.println(name);
}
14.3 Using forEach()
names.forEach(name -> System.out.println(name));
14.4 Using an Iterator
import java.util.Iterator;
Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Use an enhanced for loop or forEach() for simple traversal. Use an iterator when you need iterator-supported removal during traversal. Avoid unnecessary index-based access when working with a list implementation whose indexed access is expensive.
15. Sorting an ArrayList
You can sort an ArrayList using Collections.sort() or the List interface's sort() method. For custom ordering, provide a Comparator.
15.1 Sorting Numbers
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SortNumbers {
public static void main(String[] args) {
List<Integer> numbers =
new ArrayList<>(List.of(50, 10, 40, 20, 30));
Collections.sort(numbers);
System.out.println(numbers);
}
}
Output:
[10, 20, 30, 40, 50]
15.2 Sorting Strings
List<String> names =
new ArrayList<>(List.of("Rahul", "Aarav", "Priya"));
Collections.sort(names);
System.out.println(names);
Output:
[Aarav, Priya, Rahul]
15.3 Sorting in Reverse Order
numbers.sort(Collections.reverseOrder());
System.out.println(numbers);
This sorts the numbers in descending order using their natural ordering in reverse.
16. Allowing Duplicate Values and Null Elements
ArrayList allows duplicate values and permits null elements. This behavior can be useful, but it is important to consider how duplicates and null values affect application logic.
List<String> items = new ArrayList<>();
items.add("Pen");
items.add("Book");
items.add("Pen");
items.add(null);
System.out.println(items);
Output:
[Pen, Book, Pen, null]
Unlike List.of(), which rejects null elements, ArrayList allows them. If null values are not meaningful in your application, validate input before adding it to the list.
17. Generics and Type Safety
Generics allow you to specify which type of elements an ArrayList can store. This helps the compiler catch incompatible values before the program runs.
Example with Generics
List<Integer> marks = new ArrayList<>();
marks.add(80);
marks.add(90);
marks.add(75);
// marks.add("Excellent"); // Compile-time error
Because the list is declared as List<Integer>, only Integer values can be added. Java supports autoboxing, so an integer literal such as 80 is automatically converted into an Integer object.
Avoid Raw Types
// Avoid this:
ArrayList data = new ArrayList();
// Prefer this:
ArrayList<String> data = new ArrayList<>();
Raw types bypass generic type checking and may lead to runtime casting errors. Use parameterized collection types whenever possible.
18. ArrayList and LinkedList Comparison
| Feature |
ArrayList |
LinkedList |
| Internal structure |
Resizable array. |
Doubly linked nodes. |
| Access by index |
Typically fast. |
Typically requires traversal. |
| Appending elements |
Amortized constant time under typical conditions. |
Constant time at the end under typical conditions. |
| Insertion in the middle |
May shift subsequent elements. |
Requires traversal to the position, then relinking nodes. |
| Memory overhead |
Stores an array of references with possible unused capacity. |
Stores node links in addition to element references. |
| Best suited for |
Frequent indexed reads and general-purpose lists. |
Specific workloads that benefit from deque operations or node-based insertion after locating a position. |
ArrayList is a good default choice for many everyday list requirements. Do not assume LinkedList is always faster for insertions: finding the insertion position can itself require traversal. Evaluate the actual access pattern before choosing.
19. Understanding ArrayList Capacity and Performance
ArrayList uses an internal array to hold references to elements. When the internal array cannot accommodate additional elements, the implementation grows its storage. The exact growth policy is an implementation detail and should not be relied on by application code.
- get(index): Typically O(1) time.
- set(index, element): Typically O(1) time.
- add(element) at the end: Amortized O(1) time.
- Insert or remove in the middle: Typically O(n) because elements may need to shift.
- Search using contains() or indexOf(): Typically O(n).
These are general complexity expectations for ArrayList, not guarantees for every possible implementation environment or operation.
Using ensureCapacity()
ArrayList<Integer> numbers = new ArrayList<>();
numbers.ensureCapacity(1000);
for (int i = 1; i <= 1000; i++) {
numbers.add(i);
}
System.out.println(numbers.size());
Output:
1000
ensureCapacity() can help reduce repeated reallocations when the expected number of elements is known. It does not add elements to the list.
20. Converting Between Arrays and ArrayLists
Java provides ways to convert arrays to lists and lists to arrays. Remember that some conversion methods return fixed-size or unmodifiable lists, so choose the method according to whether you need to modify the result.
20.1 Array to a Modifiable ArrayList
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
String[] languages = {"Java", "Python", "SQL"};
List<String> list = new ArrayList<>(
Arrays.asList(languages)
);
list.add("HTML");
System.out.println(list);
Output:
[Java, Python, SQL, HTML]
20.2 ArrayList to an Array
List<String> languages =
new ArrayList<>(List.of("Java", "Python", "SQL"));
String[] array = languages.toArray(new String[0]);
System.out.println(array[0]);
Output:
Java
21. Creating a Sublist
The subList(fromIndex, toIndex) method returns a view of a selected range of elements. The starting index is inclusive and the ending index is exclusive.
List<String> subjects = new ArrayList<>(
List.of("Java", "SQL", "HTML", "CSS", "Python")
);
List<String> selected = subjects.subList(1, 4);
System.out.println(selected);
Output:
[SQL, HTML, CSS]
A sublist is backed by the original list, not an independent copy. Changes to the sublist may affect the original list, and structural changes to the original list outside the sublist can make the view's behavior undefined. Create a new ArrayList from the sublist when an independent modifiable copy is required.
List<String> independentCopy =
new ArrayList<>(subjects.subList(1, 4));
22. Common Errors and Troubleshooting
| Error or Problem |
Cause |
Solution |
IndexOutOfBoundsException |
Using an invalid index. |
Check that the index is between 0 and size() - 1 for element access. |
UnsupportedOperationException |
Trying to modify an unmodifiable or fixed-size list. |
Create a modifiable ArrayList if changes are required. |
ClassCastException |
Using raw collections or performing invalid casts. |
Use generics and compatible types. |
ConcurrentModificationException |
Changing the list structurally during fail-fast iteration in an unsupported way. |
Use an iterator's supported removal method or another suitable approach. |
| Unexpected removal |
Confusing an integer index with an Integer value. |
Use Integer.valueOf(value) when removing an integer by value. |
| Unexpected duplicate entries |
List allows duplicates. |
Check for existing values or consider using a Set when uniqueness is required. |
| Unexpected list size |
Confusing capacity with element count. |
Use size() to count actual elements. |
23. Best Practices for Working with List and ArrayList
- Declare list variables using the List interface when practical.
- Use generics to provide compile-time type safety.
- Use ArrayList for general-purpose lists and frequent index-based reads.
- Validate indexes before accessing elements when indexes come from user input.
- Use
isEmpty() to check whether a list contains no elements.
- Use
contains() to test for an existing value.
- Use
Integer.valueOf() to remove an Integer by value rather than by index.
- Use iterators correctly when removing elements during traversal.
- Remember that
subList() returns a view rather than an independent copy.
- Avoid assuming ArrayList is thread-safe.
- Prefer readable code over unnecessary manual manipulation of list indexes.
- Measure performance for large or performance-sensitive applications rather than relying on assumptions.
24. Practical Project: Student Marks Management System
Objective: Create a Java program that stores student marks in an ArrayList, displays the values, calculates the average, finds the highest mark, updates a value, and removes a record.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class StudentMarksManager {
public static void main(String[] args) {
List<Integer> marks = new ArrayList<>();
marks.add(85);
marks.add(92);
marks.add(78);
marks.add(88);
marks.add(95);
System.out.println("Student marks: " + marks);
System.out.println("Total students: " + marks.size());
int total = 0;
for (int mark : marks) {
total += mark;
}
double average = (double) total / marks.size();
System.out.println("Average marks: " + average);
System.out.println("Highest marks: " + Collections.max(marks));
marks.set(2, 82);
System.out.println("After updating: " + marks);
marks.remove(Integer.valueOf(88));
System.out.println("After removing 88: " + marks);
Collections.sort(marks);
System.out.println("Sorted marks: " + marks);
}
}
Expected Output
Student marks: [85, 92, 78, 88, 95]
Total students: 5
Average marks: 87.6
Highest marks: 95
After updating: [85, 92, 82, 88, 95]
After removing 88: [85, 92, 82, 95]
Sorted marks: [82, 85, 92, 95]
Project Enhancements
- Accept marks from the keyboard using Scanner.
- Validate that each mark falls between 0 and 100.
- Find the lowest mark using
Collections.min().
- Display only marks greater than or equal to 80.
- Count how many students passed based on a selected passing score.
- Store student names alongside marks using a separate model class or a Map.
25. Practice Exercises
- Create an ArrayList of five programming languages and print every element.
- Add an element at a specific index and observe how the order changes.
- Replace the second element using
set().
- Remove an element by its value and then remove another by index.
- Find the first and last indexes of a duplicate value.
- Sort a list of integers in ascending and descending order.
- Convert a String array into a modifiable ArrayList.
- Create a sublist and then make an independent copy of it.
- Write a program that calculates the average of values stored in an ArrayList.
- Build a shopping list program that supports adding, displaying, updating, and removing items.
26. Interview Questions and Answers
Q1. What is the List interface in Java?
Answer: List is an interface in the Java Collections Framework that represents an ordered collection with positional access. It generally permits duplicates.
Q2. What is ArrayList?
Answer: ArrayList is a resizable-array implementation of the List interface. It supports dynamic storage and efficient index-based access.
Q3. Can we create an object of List directly?
Answer: No. List is an interface. Create an object of a class that implements it, such as ArrayList or LinkedList.
Q4. What is the difference between add() and set()?
Answer: add() inserts an element, while set() replaces an element at an existing index without changing the list's size.
Q5. Does ArrayList allow duplicate elements?
Answer: Yes. ArrayList generally permits duplicates and maintains their positions in the list.
Q6. Does ArrayList allow null?
Answer: Yes. ArrayList permits null elements, although applications may choose to reject null values through validation.
Q7. What is the difference between size and capacity?
Answer: Size is the number of elements currently stored. Capacity is the size of the internal array available to hold elements before additional storage is needed.
Q8. How do you remove an element by value from List<Integer>?
Answer: Use remove(Integer.valueOf(value)) to select the overload that removes a matching Integer value rather than an element at an index.
Q9. Is ArrayList synchronized?
Answer: No. ArrayList does not automatically synchronize its operations. Shared mutable lists require an appropriate synchronization or concurrency strategy.
Q10. What is the time complexity of get() in ArrayList?
Answer: Index-based retrieval is typically O(1), because ArrayList uses an array internally.
Q11. What happens if an invalid index is used?
Answer: Operations such as get(), set(), and indexed remove() throw an IndexOutOfBoundsException when the index is invalid.
Q12. What does subList() return?
Answer: It returns a view of a range within the original list. It is not automatically an independent copy.
27. Quick Revision Checklist
- List: Interface representing an ordered collection.
- ArrayList: Resizable-array implementation of List.
- add(): Adds an element.
- get(): Retrieves an element by index.
- set(): Replaces an element at an index.
- remove(): Removes an element by index or matching value, depending on the overload.
- size(): Returns the number of elements.
- contains(): Checks whether a matching element exists.
- indexOf(): Returns the first matching index or -1.
- lastIndexOf(): Returns the last matching index or -1.
- Collections.sort(): Sorts a list by natural ordering.
- Generics: Provide compile-time type safety.
- ArrayList: Typically provides O(1) index access and amortized O(1) append.
- subList(): Returns a backed view of a selected range.
28. Conclusion
The List interface and ArrayList class are essential concepts in Core Java. List defines the operations for ordered collections, while ArrayList provides a resizable-array implementation that is suitable for many everyday programming tasks.
By practising insertion, retrieval, updating, removal, searching, sorting, iteration, and array conversion, you can develop a strong understanding of list operations. These concepts are useful in real-world applications, data processing, and Java technical interviews.
29. Additional Learning Resources
End of Notes: Working with List and ArrayList in Java